home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
ClutFade 1.3.2
/
C
/
clut_fade 1.3.2 source & libs
/
fade.c
< prev
next >
Wrap
Text File
|
1996-04-23
|
11KB
|
336 lines
/********************************************************************************
PROJECT: clut_fade.π
FILE: fade.c
PURPOSE: 'clut' fading functions
??/??/93 1.0 written by N. Jonas Englund
07/26/94 1.1 Changes by Mark Womack to allow fading all monitors, only the
main monitor, or all monitors except the main monitor. Cleaned
up the fade.h to hide more structures, and removed almost all global
space used (My changes grew the global space by 10 times so I figured
it needed to be fixed). Current code is limited to 10 monitors max,
but is easily cofigurable for more if you think you need it.
10/21/94 Changes by Mark Womack to make pascal friendly, fix < 256 color
crasher, cleaned up to make more readable.
10/24/94 Integrated fade_to_clut function written by Macneil Shonle.
Added copy_gdevice_clut function to make it easier to save
and restore device clut's.
Added fade_to_color function which uses both the fade_to_clut
and copy_gdevice_clut functions to fade to a given rgb value.
04/22/96 Fixed bug found by David Padilla. Fade routines changed the ctSeed
value of color tables, which slows subsequent calls to CopyBits.
Now restore or set the ctSeed value back to original value.
=-=-= PLEASE SEE THE README THAT ACCOMPANIED THIS PROJECT FOR DETAILS =-=-=
This software is considered Public Domain. You are free to use it in any
manner you wish. You are free to upload it to your favorite service, but
you must post it with the accompanying readme and description files.
If you use or appreciate it, please let us know!! We all love to get email.
See the addresses below.
This software is offered 'as is'. The authors are not responsible for any
damages caused by bugs or defects that might be lurking. But if it blows up
your monitor, please let us know. If you find any bugs, problems, enhancements,
please contact us.
Email Addresses: MarkWomack@aol.com, MacneilS@aol.com, KenLong@aol.com.
********************************************************************************/
//================================= INCLUDES ====================================
#include "fade.h"
//================================= DEFINES =====================================
#define MAXCOLORS 256 // supports 256 colors max
#define gMaxDevices 10 // supports only 10 monitors max
//================================= TYPEDEFS ====================================
typedef struct FadeValues
{
short reds[MAXCOLORS];
short greens[MAXCOLORS];
short blues[MAXCOLORS];
}
FadeValues;
//================================= FUNCTIONS ===================================
static void copy_cluts (GDHandle, CTabHandle*, CTabHandle*, short);
static void calc_fade (long, CTabHandle, FadeValues*);
static void fade_out (long, CTabHandle, FadeValues);
static void fade_in (long, CTabHandle, CTabHandle, FadeValues);
static void black_out (CTabHandle);
static void restore_clut(CTabHandle, CTabHandle);
//===== PUBLIC FUNCTIONS =====//
/********************************** fade_to_black ******************************/
pascal void fade_to_black(long numSteps, short fadeFlags, Boolean fadeOut)
{
GDHandle oldDev, hGD;
GDHandle gdHdls[gMaxDevices]; // list of valid graphic devices
FadeValues rgbs[gMaxDevices]; // fade values
CTabHandle gFade[gMaxDevices], // 'clut' to alter with fading functions
gOrig[gMaxDevices]; // 'clut' to hold a copy of original
short x,numDevices,stepCount;
// initialize
oldDev = GetGDevice();
hGD = (!!(fadeFlags & fadeMainOnly != 0)) ? GetMainDevice() : GetDeviceList();
numDevices = 0;
// make a list of the affected gdevices
while (hGD && numDevices < gMaxDevices)
{
// skip main device if fadeAllButMain flag
if (TestDeviceAttribute(hGD,mainScreen) && (!!(fadeFlags & fadeAllButMain)))
{
hGD = (GDHandle)(*hGD)->gdNextGD;
continue;
}
if (TestDeviceAttribute(hGD,screenDevice))
{
gdHdls[numDevices] = hGD;
numDevices++;
}
// stop now if only fading main device
if (!!(fadeFlags & fadeMainOnly != 0))
break;
hGD = (GDHandle)(*hGD)->gdNextGD;
}
// calculate the fade cluts for each device
for (x = 0; x < numDevices; x++)
{
SetGDevice(gdHdls[x]);
copy_cluts(gdHdls[x], &gFade[x], &gOrig[x], x);
calc_fade(numSteps, gFade[x], &rgbs[x]);
}
// fade each device
// I know this is unreadable (dontcha love C?), the idea is to count down on
// fadeout and count up on fade in.
for (stepCount = fadeOut ? numSteps : 0; fadeOut ? stepCount >= 0 : stepCount < numSteps; fadeOut ? stepCount-- : stepCount++)
{
for (x = 0; x < numDevices; x++)
{
SetGDevice(gdHdls[x]);
if (fadeOut)
fade_out(stepCount, gFade[x], rgbs[x]);
else
fade_in(stepCount, gFade[x], gOrig[x], rgbs[x]);
}
}
// restore each devices clut, and dispose of temp memory
for (x = 0; x < numDevices; x++)
{
SetGDevice(gdHdls[x]);
restore_clut(gFade[x], gOrig[x]);
DisposeHandle((Handle)gOrig[x]);
}
// set original device
SetGDevice(oldDev);
}
/*********************************** fade_to_clut *******************************/
pascal void fade_to_clut(long numSteps, CTabHandle destTab, GDHandle aGDevice )
{
CTabHandle srcTab = (**(**aGDevice).gdPMap).pmTable; // get the monitor’s current clut
long redDelta[MAXCOLORS]; // We want the range for each color to be of an
long greenDelta[MAXCOLORS]; // unsigned short, but we need negative numbers.
long blueDelta[MAXCOLORS]; // So these longs are the solution.
long difference; // used to clear up clutter in the code
long i; // to cycle trough for loops
long colorIndex; // to cycle through arrays
GDHandle oldGDevice;
oldGDevice = GetGDevice(); // save the old
SetGDevice( aGDevice ); // set it to the monitor to be faded
/**** Set up the deltas ****/
for( i=0; i <= (**destTab).ctSize; i++ )
{ /* This is what I am thinking: take the difference between the two colors and divide
it by the number of steps (numSteps). So we will have a number that can be added
to the source numSteps times and have it end up equaling the destination.
*/
difference = ( (long)(**srcTab).ctTable[i].rgb.red - (long)(**destTab).ctTable[i].rgb.red );
redDelta[i] = difference / (long)numSteps;
difference = ( (long)(**srcTab).ctTable[i].rgb.green - (long)(**destTab).ctTable[i].rgb.green );
greenDelta[i] = difference / (long)numSteps;
difference = ( (long)(**srcTab).ctTable[i].rgb.blue - (long)(**destTab).ctTable[i].rgb.blue );
blueDelta[i] = difference / (long)numSteps;
}
/**** Do the fade ****/
for( i = 0; i < numSteps; i++ )
{
for( colorIndex = 0; colorIndex <= (**destTab).ctSize; colorIndex++ )
{ // make the source more and more like the dest
(**srcTab).ctTable[colorIndex].rgb.red -= redDelta[colorIndex];
(**srcTab).ctTable[colorIndex].rgb.green -= greenDelta[colorIndex];
(**srcTab).ctTable[colorIndex].rgb.blue -= blueDelta[colorIndex];
}
SetEntries( 0, (**srcTab).ctSize, (ColorSpec *)&(**srcTab).ctTable );
}
SetEntries( 0, (**destTab).ctSize, (ColorSpec *)&(**destTab).ctTable ); // set it to the dest, just in case
(**srcTab).ctSeed = (**destTab).ctSeed; // set the ctSeed as well!
MakeITable( nil, nil, 0 );
SetGDevice( oldGDevice ); // return it back to it’s old state
}
pascal void fade_to_color(long numSteps, RGBColor* destColor, GDHandle aGDevice )
{
CTabHandle newColors;
short x;
// get copy of the current color table
copy_gdevice_clut(aGDevice,&newColors);
// make the color table all one color
for( x = 0; x <= (**newColors).ctSize; x++ )
(**newColors).ctTable[x].rgb = *destColor;
// change the ctSeed so it is different than original
(**newColors).ctSeed = GetCTSeed();
// fade to the custom color table
fade_to_clut(numSteps,newColors,aGDevice);
// dispose color table
DisposeHandle((Handle)newColors);
}
pascal void copy_gdevice_clut(GDHandle aGDevice, CTabHandle* copyOfClut)
{
CTabHandle srcTab = (**(**aGDevice).gdPMap).pmTable; // get the monitor’s current clut
HandToHand((Handle*)&srcTab);
*copyOfClut = srcTab;
}
//===== PRIVATE FUNCTIONS =====//
/********************************** copy_cluts **********************************/
static
void copy_cluts(GDHandle hGD, CTabHandle* gFade, CTabHandle* gOrig, short arrayPos)
{
Handle gTempH; // temporary handle to copy 'clut'
*gFade = (*(*hGD)->gdPMap)->pmTable;
gTempH = (Handle) (*(*hGD)->gdPMap)->pmTable;
HandToHand(&gTempH);
*gOrig = (CTabHandle) gTempH;
HLock((Handle) *gFade);
HLock((Handle) *gOrig);
}
/*********************************** calc_fade **********************************/
static
void calc_fade(long numSteps, CTabHandle gFade, FadeValues *rgbs)
{
short i;
for (i = 0; i <= (*gFade)->ctSize; i++)
{
rgbs->reds[i] = (*gFade)->ctTable[i].rgb.red / numSteps;
rgbs->greens[i] = (*gFade)->ctTable[i].rgb.green / numSteps;
rgbs->blues[i] = (*gFade)->ctTable[i].rgb.blue / numSteps;
}
}
/*********************************** fade_out ***********************************/
static
void fade_out(long fadeLevel, CTabHandle gFade, FadeValues rgbs)
{
short i;
for (i = 0; i <= (*gFade)->ctSize; i++)
{
if ((*gFade)->ctTable[i].rgb.red > rgbs.reds[i])
(*gFade)->ctTable[i].rgb.red -= rgbs.reds[i];
if ((*gFade)->ctTable[i].rgb.green > rgbs.greens[i])
(*gFade)->ctTable[i].rgb.green -= rgbs.greens[i];
if ((*gFade)->ctTable[i].rgb.blue > rgbs.blues[i])
(*gFade)->ctTable[i].rgb.blue -= rgbs.blues[i];
}
SetEntries(0, (*gFade)->ctSize, (*gFade)->ctTable);
if (fadeLevel == 0)
black_out(gFade);
}
/************************************ fade_in ***********************************/
static
void fade_in(long fadeLevel, CTabHandle gFade, CTabHandle gOrig, FadeValues rgbs)
{
short i;
if (fadeLevel == 0)
black_out(gFade);
for (i = 0; i <= (*gFade)->ctSize; i++)
{
if ((*gFade)->ctTable[i].rgb.red < (*gOrig)->ctTable[i].rgb.red)
(*gFade)->ctTable[i].rgb.red += rgbs.reds[i];
if ((*gFade)->ctTable[i].rgb.green < (*gOrig)->ctTable[i].rgb.green)
(*gFade)->ctTable[i].rgb.green += rgbs.greens[i];
if ((*gFade)->ctTable[i].rgb.blue < (*gOrig)->ctTable[i].rgb.blue)
(*gFade)->ctTable[i].rgb.blue += rgbs.blues[i];
}
SetEntries(0, (*gFade)->ctSize, (*gFade)->ctTable);
}
/*********************************** black_out **********************************/
static
void black_out(CTabHandle gFade)
{
short i;
for (i = 0; i <= (*gFade)->ctSize; i++)
{
(*gFade)->ctTable[i].rgb.red = 0;
(*gFade)->ctTable[i].rgb.green = 0;
(*gFade)->ctTable[i].rgb.blue = 0;
}
SetEntries(0, (*gFade)->ctSize, (*gFade)->ctTable);
}
/********************************** restore_clut ********************************/
static
void restore_clut(CTabHandle gFade, CTabHandle gOrig)
{
short i;
for (i = 0; i <= (*gFade)->ctSize; i++)
{
(*gFade)->ctTable[i].rgb.red = (*gOrig)->ctTable[i].rgb.red;
(*gFade)->ctTable[i].rgb.green = (*gOrig)->ctTable[i].rgb.green;
(*gFade)->ctTable[i].rgb.blue = (*gOrig)->ctTable[i].rgb.blue;
}
(*gFade)->ctSeed = (*gOrig)->ctSeed; // restore the ctSeed too!
MakeITable(nil, nil, 0);
HUnlock((Handle) gFade);
HUnlock((Handle) gOrig);
}